import logging
from fastapi import APIRouter, Request
from fastapi.responses import RedirectResponse, JSONResponse
import jwt
from datetime import datetime, timedelta
from factories.social_login_factory import SocialLoginFactory
from config.dingtalk_config import DINGTALK_OAUTH_CONFIG

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# JWT密钥，实际项目中应该从环境变量获取
SECRET_KEY = "your-secret-key-please-change-in-production"
ALGORITHM = "HS256"

def create_access_token(data: dict, expires_delta: timedelta = None):
    """创建JWT访问令牌"""
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

class SocialAuthController:
    """社交登录控制器"""
    
    @staticmethod
    async def login(provider_name: str):
        """社交登录入口"""
        try:
            # 获取配置
            config = SocialAuthController._get_provider_config(provider_name)
            if not config:
                return JSONResponse(status_code=400, content={"detail": f"不支持的登录方式: {provider_name}"})
            
            # 使用工厂模式创建提供者
            provider = SocialLoginFactory.create_provider(provider_name, config)
            if not provider:
                return JSONResponse(status_code=500, content={"detail": f"无法创建{provider_name}登录提供者"})
            
            redirect_url = await provider.get_authorization_url()
            return RedirectResponse(url=redirect_url)
        except Exception as e:
            logger.error(f"{provider_name}登录重定向失败: {str(e)}")
            return JSONResponse(status_code=500, content={"detail": f"{provider_name}登录重定向失败"})
    
    @staticmethod
    async def callback(provider_name: str, request: Request, code: str = None):
        """社交登录回调处理"""
        try:
            if not code:
                logger.warning("缺少授权码")
                return JSONResponse(status_code=400, content={"detail": "缺少授权码"})
            
            # 获取配置
            config = SocialAuthController._get_provider_config(provider_name)
            if not config:
                return JSONResponse(status_code=400, content={"detail": f"不支持的登录方式: {provider_name}"})
            
            # 使用工厂模式创建提供者
            provider = SocialLoginFactory.create_provider(provider_name, config)
            if not provider:
                return JSONResponse(status_code=500, content={"detail": f"无法创建{provider_name}登录提供者"})
            
            # 获取访问令牌
            token_response = await provider.exchange_code_for_token(code)
            
            if token_response["status_code"] != 200:
                logger.error(f"获取访问令牌失败: {token_response.get('text', '')}")
                return JSONResponse(status_code=token_response["status_code"], content={"detail": "获取访问令牌失败"})
            
            token_data = token_response["data"]
            access_token = SocialAuthController._extract_access_token(token_data, provider_name)
            
            if not access_token:
                logger.error("未获取到accessToken")
                return JSONResponse(status_code=400, content={"detail": "未获取到accessToken"})
            
            # 获取用户信息
            user_info = await provider.get_user_info(access_token)
            
            if "errcode" in user_info and user_info["errcode"] != 0:
                logger.error(f"获取用户信息失败: {user_info}")
                return JSONResponse(status_code=400, content={"detail": "获取用户信息失败"})
            
            # 保存用户信息
            user = await provider.save_user_info(user_info, token_data)
            
            # 创建JWT令牌
            access_token = create_access_token(
                data={
                    "sub": str(user.id),
                    "provider": provider_name
                },
                expires_delta=timedelta(days=7)
            )
            
            # 重定向到前端，携带token
            frontend_redirect_url = f"http://localhost:5173/login?token={access_token}"
            return RedirectResponse(url=frontend_redirect_url)
            
        except Exception as e:
            logger.error(f"{provider_name}登录回调处理失败: {str(e)}")
            return JSONResponse(status_code=500, content={"detail": f"{provider_name}登录处理失败"})
    
    @staticmethod
    def _get_provider_config(provider_name: str) -> dict:
        """获取提供者配置"""
        configs = {
            "dingtalk": DINGTALK_OAUTH_CONFIG
            # 可以在这里添加其他提供者的配置
        }
        return configs.get(provider_name)
    
    @staticmethod
    def _extract_access_token(token_data: dict, provider_name: str) -> str:
        """从不同提供者的响应中提取访问令牌"""
        token_keys = {
            "dingtalk": "accessToken",
            "wechat": "access_token",
            "github": "access_token",
            "google": "access_token"
        }
        
        key = token_keys.get(provider_name, "access_token")
        return token_data.get(key, "")